﻿<h1>Type-Unsafe Pointers</h1>

<p>
We have learned Go pointers from the article
<a href="pointer.html">pointers in Go</a>.
From that article, we know that, comparing to C pointers,
there are many restrictions made for Go pointers.
For example, Go pointers can't participate arithmetic operations,
and for two arbitrary pointer types, it is very possible that
their values can't be converted to each other.
</p>

<p>
The pointers explained in that article are called type-safe pointers actually.
Although the restrictions on type-safe pointers really make
us be able to write safe Go code with ease,
they also make some obstacles to write efficient code for some scenarios.
</p>

<p>
In fact, Go also supports type-unsafe pointers,
which are pointers without the restrictions made for safe pointers.
Type-unsafe pointers are also called unsafe pointers in Go.
Go unsafe pointers are much like C pointers,
they are powerful, and also dangerous.
For some cases, we can write more efficient code with the help of unsafe pointers.
On the other hand, by using unsafe pointers,
it is easy to write bad code which is too subtle to detect in time.
</p>

<p>
Another big risk of using unsafe pointers comes from the fact that
the unsafe mechanism is not protected by
<a href="https://golang.org/doc/go1compat">the Go 1 compatibility guidelines</a>.
Code depending on unsafe pointers works today could break
since a later Go version.
</p>

<p>
If you really desire the code efficient improvements by using unsafe
pointers for any reason, you should not only know the above mentioned risks,
but also follow the instructions written in the official Go
documentation and clearly understand the effects of each unsafe pointer use,
so that you can write safe Go code with unsafe pointers.
</p>

<h3>About the <code>unsafe</code> Standard Package</h3>

<div>
Go provides a special <a href="type-system-overview.html#type-kinds">kind of types</a> for unsafe pointers.
We must import
<a href="https://golang.org/pkg/unsafe/">the <code>unsafe</code> standard package</a>
to use unsafe pointers.
The <code>unsafe.Pointer</code> type is defined as

<pre class="disable-line-numbers111"><code class="language-go">type Pointer *ArbitraryType
</code></pre>

<p>
Surely, it is not a usual type definition.
Here the <code>ArbitraryType</code>
just hints that a <code>unsafe.Pointer</code> value can be converted
to any safe pointer values in Go (and vice versa).
In other words, <code>unsafe.Pointer</code> is like the <code>void*</code> in C language.
</p>

<p>
Go unsafe pointers mean the types
whose underlying types are <code>unsafe.Pointer</code>.
</p>

<p>
The zero values of unsafe pointers are also represented with
the predeclared identifier <code>nil</code>.
</p>

The <code>unsafe</code> standard package also provides three functions.
<ul>
<li>
	<code>func Alignof(variable ArbitraryType) uintptr</code>,
	which is used to get the address alignment of a value.
	Please notes, the aligns for struct-field values and non-field values
	of the same type may be different, though for the standard
	Go compiler, they are always the same, for gccgo compiler, they may be different.

</li>
<li>
	<code>func Offsetof(selector ArbitraryType) uintptr</code>,
	which is used to get the address offset of a field in a struct value.
	The offset is relative to the address of the struct value.
	The return results should be always the same for the same corresponding
	field of values of the same struct type in the same program.
</li>
<li>
	<code>func Sizeof(variable ArbitraryType) uintptr</code>,
	which is used to get the size of a value
	(a.k.a., the size of the type of the value).
	The return results should be always the same
	for all values of the same type in the same program.
</li>
</ul>

<p>
Note that the types of the return results of the three functions are all
<code>uintptr</code>. Below we will learn that uintptr values
can be converted to unsafe pointers (and vice versa).
</p>

<p>
Although the return results of calls of any of the three functions
are consistent in the same program,
they might be different crossing operating systems, crossing architectures,
crossing compilers, and crossing compiler versions.
</p>

<p>
Calls to the three functions are always evaluated at compile time.
Their return results can be assigned/bound to named constants.
</p>

An example of using the three functions.
<pre class="line-numbers"><code class="language-go">package main

import "fmt"
import "unsafe"

func main() {
	var x struct {
		a int64
		b bool
		c string
	}
	const M, N = unsafe.Sizeof(x.c), unsafe.Sizeof(x)
	fmt.Println(M, N) // 16 32

	fmt.Println(unsafe.Alignof(x.a)) // 8
	fmt.Println(unsafe.Alignof(x.b)) // 1
	fmt.Println(unsafe.Alignof(x.c)) // 8

	fmt.Println(unsafe.Offsetof(x.a)) // 0
	fmt.Println(unsafe.Offsetof(x.b)) // 8
	fmt.Println(unsafe.Offsetof(x.c)) // 16
}
</code></pre>

<p>
Please note, the print results shown in the comments are for the standard
Go compiler version 1.13 on Linux AMD64 architecture.
</p>

</div>

<!--
todo: remove most this section, except the Ian confirmed points,
      move the confirmed points to the last section.

<h3>The Warnings From Go Official Documentation</h3>

<div>

The <code>unsafe</code> package documentation
<a href="https://golang.org/pkg/unsafe/#pkg-overview">says</a>:

<div class="alert alert-success">
Packages that import <code>unsafe</code> may be non-portable
and are not protected by the Go 1 compatibility guidelines.
</div>

And the <a href="https://golang.org/doc/go1compat">Go 1 compatibility guidelines</a> says:
<div class="alert alert-success">
Packages that import <code>unsafe</code> may depend on internal properties of the Go implementation.
We reserve the right to make changes to the implementation that may break such programs.
</div>

However, Ian, one of the core member of Go team,
has <a href="https://groups.google.com/forum/?_escaped_fragment_=topic/golang-nuts/Pi7VveWDUPc">confirmed</a>:
<ul>
<li>
	the signatures of the functions in <code>unsafe</code> package
	will not change in future Go 1 versions,
</li>
<li>
	and the <code>unsafe.Pointer</code> type will
	always there in future Go 1 versions.
</li>
</ul>

<p>
So, the three functions provided in the <code>unsafe</code> package
don't look much dangerous.
Rob Pike, the Go project leader, even
<a href="https://github.com/golang/go/issues/5602">made a proposal to move
the three functions to elsewhere</a>.
The only unsafety of these functions is their calls
may return different values for later versions of Go compilers.
</p>

<p>
Most of the unsafty of the <code>unsafe</code> package comes unsafe pointers.
They are as dangerous as C pointers, which is Go always tries to avoid.
</p>

</div>
-->

<h3>Unsafe Pointers Related Conversion Rules</h3>

<div>
Currently (Go 1.13), Go compilers allow the following explicit conversions.
<ul>
<li>
	A safe pointer can be explicitly converted to an unsafe pointer,
	and vice versa.
</li>
<li>
	An uintptr value can be explicitly converted to an unsafe pointer,
	and vice versa.
	But please note, a nil unsafe.Pointer shouldn't be converted to uintptr and back with arithmetic.
</li>
</ul>

<p>
By using these conversions, we can convert a safe pointer value to an arbitrary safe pointer type.
</p>

<p>
However, although these conversions are all legal at compile time,
not all of them are valid (safe) at run time.
These conversions defeat the memory safety the whole Go type system
(except the unsafe part) tries to maintain.
We must follow the instructions listed in a later section below
to write valid Go code with unsafe pointers.
</p>

</div>

<h3>Some Facts in Go We Should Know</h3>

<p>
Before introducing the valid unsafe pointer use patterns,
we need to know some facts in Go.
</p>

<h4>Fact 1: unsafe pointers are pointers and uintptr values are integers</h4>

<p>
Each of non-nil safe and unsafe pointers references another value.
However uintptr values don't reference any values, they are just plain integers,
though often each of them stores an integer which can be used to represent a memory address.
</p>

<p>
Go is a language supporting automatic garbage collection.
When a Go program is running, Go runtime will
<a href="memory-block.html#when-to-collect">check which memory blocks are not used
by any value any more and collect the memory</a> allocated for these unused blocks,
from time to time.
Pointers play an important role in the check process.
If a memory block is unreachable from (referenced by) any values still in using,
then Go runtime thinks it is an unused value and it can be safely garbage collected.
</p>

<p>
As uintptr values are integers, they can participate arithmetic operations.
</p>

<p>
The example in the next subsection shows the differences between
pointers and uintptr values.
</p>

<h4>Fact 2: unused memory blocks may be collected at any time</h4>

<div>
<p>
At run time, the garbage collector may run at an uncertain time,
and each garbage collection process may last an uncertain duration.
So when a memory block becomes unused, it may be
<a href="memory-block.html#when-can-collect">collected at an uncertain time</a>.
</p>

For example:

<pre class="line-numbers"><code class="language-go">import "unsafe"

// Assume createInt will not be inlined.
func createInt() *int {
	return new(int)
}

func foo() {
	p0, y, z := createInt(), createInt(), createInt()
	var p1 = unsafe.Pointer(y)
	var p2 = uintptr(unsafe.Pointer(z))

	// At the time, even if the address of the int
	// value referenced by z is still stored in p2,
	// the int value has already become unused, so
	// garbage collector can collect the memory
	// allocated for it now. On the other hand, the
	// int values referenced by p0 and p1 are still
	// in using.

	// uintptr can participate arithmetic operations.
	p2 += 2; p2--; p2--

	*p0 = 1                          // okay
	*(*int)(p1) = 2                  // okay
	*(*int)(unsafe.Pointer(p2))) = 3 // dangerous!
}
</code></pre>

<p>
In the above example, the fact that value <code>p2</code> is still in using can't guarantee
that the memory block ever hosting the <code>int</code> value referenced by <code>z</code> has not been garbage collected yet.
In other words, when <code>*(*T)(unsafe.Pointer(p2))) = 3</code> is executed, the memory block may be collected, or not.
It is dangerous to dereference the address stored in value <code>p2</code> to an <code>int</code> value,
for it is possible that the memory block has been already reallocated for another value (even for another program).
</p>

</div>

<a class="anchor" id="fact-value-address-might-change"></a>
<h4>Fact 3: the addresses of some values might change at run time</h4>

<p>
Please read the article <a href="memory-block.html#where-to-allocate">memory blocks</a> for details (see the end of the hyperlinked section).
Here, we should just know that when the size of the stack of a goroutine changes,
the memory blocks allocated on the stack will be moved.
In other words, the addresses of the values hosted on these memory blocks will change.
</p>

<h4>Fact 4: we can use a <code>runtime.KeepAlive</code> function call to mark a value as still in using (reachable) before the call</h4>

<div>
<p>
To mark a value and the value parts referenced by it still reachable, we should pass a value which references
the value as the argument of a <code>runtime.KeepAlive</code> function call.
A pointer to the value is often used as such an argument.
</p>

For example, by appending a <code>runtime.KeepAlive(&amp;z)</code>
call to the example in the last subsection,
<code>*(*T)(unsafe.Pointer(p2))) = 3</code> can be executed safely now.

<pre class="line-numbers"><code class="language-go">func foo() {
	p0, y, z := createInt(), createInt(), createInt()
	var p1 = unsafe.Pointer(y)
	var p2 = uintptr(unsafe.Pointer(z))

	p2 += 2; p2--; p2--

	*p0 = 1
	*(*int)(p1) = 2
	*(*int)(unsafe.Pointer(p2))) = 3 // safe now!

	runtime.KeepAlive(&z) // This line k
}
</code></pre>

<p>
</p>

</div>

<h4>Fact 5: the reachable range of a value at run time may be not as large as it looks in code</h4>


<div>
<p>
In the following example, the fact value <code>t</code> is still in using
can't guarantee that the values referenced by value <code>t.y</code> are still in using.
</p>

<pre class="line-numbers"><code class="language-go">type T struct {
	x int
	y *[1<<23]byte
}

func bar() {
	t := T{y: new([1<<23]byte)}
	p := uintptr(unsafe.Pointer(&t.y[0]))

	... // use T.x and T.y

	// A smart compiler can detect that the value
	// t.y will never be used again and think the
	// memory block hosting t.y can be collected now.

	// Using *(*byte)(unsafe.Pointer(p))) is
	// dangerous here.

	// Continue using value t, but only use its x field.
	println(t.x)
}
</code></pre>

<p>
</p>

</div>

<h4>Fact 6: <code>*unsafe.Pointer</code> is a general safe pointer type</h4>

<div>
<p>
Yes, <code>*unsafe.Pointer</code> is a safe pointer type.
Its base type is <code>unsafe.Pointer</code>.
As it is a safe pointer, according the conversion rules listed above,
it can be converted to <code>unsafe.Pointer</code> type, and vice versa.
</p>

For example:

<pre class="line-numbers"><code class="language-go">package main

import "unsafe"

func main() {
	x := 123                // of type int
	p := unsafe.Pointer(&x) // of type unsafe.Pointer
	pp := &p                // of type *unsafe.Pointer
	p = unsafe.Pointer(pp)
	pp = (*unsafe.Pointer)(p)
}
</code></pre>

</div>

<h3>How to Use Unsafe Pointers Correctly?</h3>

<p>
The <code>unsafe</code> standard package documentation lists
<a href="https://golang.org/pkg/unsafe/#Pointer">six unsafe pointer use patterns</a>.
Following will introduce and explain them one by one.
</p>

<h4>Pattern 1: convert a <code>*T1</code> value to unsafe Pointer, then convert the unsafe pointer value to <code>*T2</code>.</h4>

<div>

<p>
As mentioned above, by using the unsafe pointer conversion rules above,
we can convert a value of <code>*T1</code> to type <code>*T2</code>,
where <code>T1</code> and <code>T2</code> are two arbitrary types.
However, we should only do such conversions if the size of <code>T1</code>
is no larger than <code>T2</code>, and only if the conversions are meaningful.
</p>

<p>
As a result, we can also achieve the conversions between
type <code>T1</code> and <code>T2</code> by using this pattern.
</p>

One example is the <code>math.Float64bits</code> function,
which converts a <code>float64</code> value to an <code>uint64</code> value,
without changing any bit in the <code>float64</code> value.
The <code>math.Float64bits</code> function does reverse conversions.

<pre class="line-numbers"><code class="language-go">func Float64bits(f float64) uint64 {
	return *(*uint64)(unsafe.Pointer(&f))
}

func Float64frombits(b uint64) float64 {
	return *(*float64)(unsafe.Pointer(&b))
}
</code></pre>

<p>
Please note, the return result of the <code>math.Float64bits(aFloat64)</code>
function call is different from the result of the explicit conversion
<code>uint64(aFloat64)</code>.
</p>

In the following example, we use this pattern to convert a <code>[]MyString</code>
slice to type <code>[]string</code>, and vice versa.
The result slice and the original slice share the underlying elements.
Such conversions are impossible through safe ways,

<pre class="line-numbers"><code class="language-go">package main

import (
	"fmt"
	"unsafe"
)

func main() {
	type MyString string
	ms := []MyString{"C", "C++", "Go"}
	fmt.Printf("%s\n", ms)  // [C C++ Go]
	// ss := ([]string)(ms) // compiling error
	ss := *(*[]string)(unsafe.Pointer(&ms))
	ss[1] = "Rust"
	fmt.Printf("%s\n", ms) // [C Rust Go]
	// ms = []MyString(ss) // compiling error
	ms = *(*[]MyString)(unsafe.Pointer(&ss))
}
</code></pre>

<p>
</p>

</div>

<h4>Pattern 2: convert unsafe pointer to uintptr, then use the uintptr value.</h4>

<div>
<p>
This pattern is not very useful.
Usually, we print the result uintptr values to check the memory addresses
stored in them. However, there are other less verbose ways to this job.
So this pattern is not much useful.
</p>

Example:
<pre class="line-numbers"><code class="language-go">package main

import "fmt"
import "unsafe"

func main() {
	type T struct{a int}
	var t T
	fmt.Println(&t) // &{0}
	println(&t)     // 0xc6233120a8
	// The next line print: c6233120a8
	fmt.Printf("%x\n", uintptr(unsafe.Pointer(&t)))
}
</code></pre>

<p>
The outputted addresses might be different for each run.
</p>
</div>

<a class="anchor" id="pattern-convert-to-uintptr-and-back"></a>
<h4>Pattern 3: convert unsafe pointer to uintptr, do arithmetic operations with the uintptr value, then convert it back</h4>

<div>

For example:
<pre class="line-numbers"><code class="language-go">package main

import "fmt"
import "unsafe"

type T struct {
	x bool
	y [3]int16
}

const N = unsafe.Offsetof(T{}.y)
const M = unsafe.Sizeof([3]int16{}[0])

func main() {
	t := T{y: [3]int16{123, 456, 789}}
	p := unsafe.Pointer(&t)
	// "uintptr(p)+N+M+M" is the address of t.y[2].
	ty2 := (*int16)(unsafe.Pointer(uintptr(p)+N+M+M))
	fmt.Println(*ty2) // 789
}
</code></pre>

<p>
</p>

Please note, in this specified example,
the conversion <code>unsafe.Pointer(uintptr(p) + N + M + M)</code>
shouldn't be split into two lines, like the following code shows.
Please read the comments in the code for the reason.

<pre class="line-numbers"><code class="language-go">func main() {
	t := T{y: [3]int16{123, 456, 789}}
	p := unsafe.Pointer(&t)
	// ty2 := (*int16)(unsafe.Pointer(uintptr(p)+N+M+M))
	addr := uintptr(p) + N + M + M
	// Now the t value becomes unused, its memory may be
	// garbage collected at this time. So the following
	// use of the address of t.y[2] may become invalid
	// and dangerous! 
	// Another potential danger is, if some operations
	// make the stack grow or shrink here, then the
	// address of t might change, so that the address
	// saved in addr will become invalid (fact 3),
	// though this danger doesn't exist for this
	// specified example.
	ty2 := (*int16)(unsafe.Pointer(addr))
	fmt.Println(*ty2)
}
</code></pre>

<p>
Such bugs are very subtle and hard to detect,
which is why the uses of unsafe pointers are dangerous.
An <code>-d=checkptr</code> option <a href="https://go-review.googlesource.com/c/go/+/162237">might be added</a> for the official Go compiler v1.14.
</p>

If we do want to split that conversion line into two lines,
we should call the <code>runtime.KeepAlive</code> function and pass the unsafe pointer <code>p</code>
(or any other value which is also referencing value <code>t.y[2]</code>) as the argument,
after the split two lines. Like this

<pre class="line-numbers"><code class="language-go">func main() {
	t := T{y: [3]int16{123, 456, 789}}
	p := unsafe.Pointer(t)
	addr := uintptr(p) + N + M + M
	ty2 := (*int16)(unsafe.Pointer(addr))
	// This following line ensures the memory of
	// the value t will not get garbage collected
	// currently for sure.
	runtime.KeepAlive(p)
	fmt.Println(*ty2)
}
</code></pre>

<p>
However, I don't recommend to use the <code>runtime.KeepAlive</code> trick for this use pattern,
for the potential another danger mentioned above.
If is possible that the stack grows when the runtime allocates memory for the variable <code>ty2</code>,
so that the address of <code>t</code> changes and the value stored in <code>addr</code> becomes invalid,
which directly leads to the value of <code>ty2</code> is also invalid.
But honestly speaking, this potential danger doesn't exist here if the code compiles with
the standard Go compiler. In the implementation of the standard Go compiler,
a <code>runtime.KeepAlive</code> call will makes its argument and the values referenced by
the argument be allocated on heap and memory blocks allocated on heap will be never moved.
</p>

<p>
Another detail which should be also noted is that,
it is not recommended to store the end boundary of a memory block
in a pointer (either safe or unsafe one).
Doing this will prevent another memory block which closely follows
the former memory block from being garbage collected.
Please read <a href="unofficial-faq.html#final-zero-size-field">this FAQ item</a> to get more explanations.
</p>

</div>

<h4>Pattern 4: convert unsafe pointers to <code>uintptr</code> values as arguments of <code>syscall.Syscall</code> calls.</h4>

<div>

From the explanations for the last pattern,
we know that the following function is dangerous.

<pre class="line-numbers"><code class="language-go">// Assume this function will not inlined.
func DoSomething(addr uintptr) {
	// read or write values at the passed address ...
}
</code></pre>

<p>
The reason why the above function is dangerous is that the function
itself can't guarantee the memory block at the passed argument address
is not garbage collected yet.
If the memory block is collected or is reallocated for other values,
then the operations made in the function body are dangerous.
</p>

However, the prototype of the <code>Syscall</code> function in
the <code>syscall</code> standard package is as
<pre class="disable-line-numbers111"><code class="language-go">func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
</code></pre>

<p>
How does this function guarantee that the memory blocks at the passed addresses
<code>a1</code>, <code>a2</code> and <code>a3</code> are still not garbage
collected yet within the function internal?
The function can't guarantee this.
In fact, compilers will make the guarantee.
It is the privilege of calls to <code>syscall.Syscall</code> alike functions.
</p>

<p>
We can think that, compilers will automatically insert some instructions
for each of the unsafe pointer arguments who are converted to <code>uintptr</code>,
like the third argument in the following <code>syscall.Syscall</code> call,
to prevent the memory block referenced by that argument from being garbage collected or moved.
</p>

The following call is safe:
<pre class="line-numbers"><code class="language-go">syscall.Syscall(SYS_READ, uintptr(fd),
			uintptr(unsafe.Pointer(p)), uintptr(n))
</code></pre>

But the following call is dangerous:

<pre class="line-numbers"><code class="language-go">u := uintptr(unsafe.Pointer(p))
// At this time, the value referenced by p might
// have become unused and been collected already,
// or the address of the value has changed.
syscall.Syscall(SYS_READ, uintptr(fd), u, uintptr(n))
</code></pre>

<p>
</p>

<p>
Again, never use this pattern when calling other functions.
</p>

</div>

<h4>Pattern 5: convert the <code>uintptr</code> result of <code>reflect.Value.Pointer</code> or <code>reflect.Value.UnsafeAddr</code> method call to unsafe pointer</h4>

<div>

<p>
The methods <code>Pointer</code> and <code>UnsafeAddr</code> of the
<code>Value</code> type in the <code>reflect</code> standard package
both return a result of type <code>uintptr</code> instead of
<code>unsafe.Pointer</code>.
This is a deliberate design, which is to avoid converting the results of calls
(to the two methods) to any safe pointer types
without importing the <code>unsafe</code> standard package.
</p>

<p>
The design requires the return result of a call to either of the two methods
must be converted to an unsafe pointer immediately after making the call.
Otherwise, there will be small time window in which the memory block allocated at the
address stored in the result might lose all references and be garbage collected.
</p>

For example, the following call is safe.

<pre class="disable-line-numbers111"><code class="language-go">p := (*int)(unsafe.Pointer(reflect.ValueOf(new(int)).Pointer()))
</code></pre>

On the other hand, the following call is dangerous.

<pre class="line-numbers"><code class="language-go">u := reflect.ValueOf(new(int)).Pointer()
// At this moment, the memory block at the address
// stored in u might have been collected already.
p := (*int)(unsafe.Pointer(u))
</code></pre>

<p>
</p>

<p>
Note: this pattern also applies to the <a href="https://golang.org/pkg/syscall/?GOOS=windows#Proc.Call">syscall.Proc.Call</a>
and <a href="https://golang.org/pkg/syscall/?GOOS=windows#LazyProc.Call">syscall.LazyProc.Call</a> methods on Windows.
</p>
</div>

<h4>Pattern 6: convert a <code>reflect.SliceHeader.Data</code> or <code>reflect.StringHeader.Data</code> field to unsafe pointer, and the inverse.</h4>

<div>
<p>
For the same reason mentioned for the last subsection, the <code>Data</code> fields
of the struct type <code>SliceHeader</code> and <code>StringHeader</code> in
the <code>reflect</code> standard package are declared with type
<code>uintptr</code> instead of <code>unsafe.Pointer</code>.
</p>

<p>
We convert a pointer to a string to a <code>*reflect.StringHeader</code> pointer value,
so that we can manipulate the internal of the string.
The same, we can convert a pointer to a slice to a <code>*reflect.SliceHeader</code> pointer value,
so that we can manipulate the internal of the slice.
</p>

An example of using <code>reflect.StringHeader</code>:

<pre class="line-numbers"><code class="language-go">package main

import "fmt"
import "unsafe"
import "reflect"

func main() {
	a := [...]byte{'G', 'o', 'l', 'a', 'n', 'g'}
	s := "Java"
	hdr := (*reflect.StringHeader)(unsafe.Pointer(&s))
	hdr.Data = uintptr(unsafe.Pointer(&a))
	hdr.Len = len(a)
	fmt.Println(s) // Golang
	// Now s and a share the same byte sequence, which
	// makes the bytes in the string s become mutable.
	a[2], a[3], a[4], a[5] = 'o', 'g', 'l', 'e'
	fmt.Println(s) // Google
}
</code></pre>

<p>
</p>

An example of using <code>reflect.SliceHeader</code>:

<pre class="line-numbers"><code class="language-go">package main

import (
	"fmt"
	"unsafe"
	"reflect"
	"runtime"
)

func main() {
	a := [6]byte{'G', 'o', '1', '0', '1'}
	bs := []byte("Golang")
	hdr := (*reflect.SliceHeader)(unsafe.Pointer(&bs))
	hdr.Data = uintptr(unsafe.Pointer(&a))
	runtime.KeepAlive(&a) // needed!
	hdr.Len = 2
	hdr.Cap = len(a)
	fmt.Printf("%s\n", bs) // Go
	bs = bs[:cap(bs)]
	fmt.Printf("%s\n", bs) // Go101
}
</code></pre>

<p>
Note, a <code>runtime.KeepAlive</code> call is needed in this example,
otherwise, the slice might reference an invalid underlying byte sequence.
</p>

In general,
we should only get a <code>*reflect.StringHeader</code> pointer value from an actual (already existed) string,
or get a <code>*reflect.SliceHeader</code> pointer value from an actual (already existed) slice.
We shouldn't do the contrary, such as creating a string from a <code>StringHeader</code>,
or creating a slice from a <code>SliceHeader</code>.
For example, the following code is dangerous.

<pre class="line-numbers"><code class="language-go">var hdr reflect.StringHeader
hdr.Data = uintptr(unsafe.Pointer(new([5]byte)))
// Now the just allocated byte array has lose all
// references and it can be garbage collected now.
hdr.Len = 5
s := *(*string)(unsafe.Pointer(&hdr)) // dangerous!
</code></pre>

<p>
</p>

The following is an example which shows how to convert a string to to a byte slice,
by using the unsafe way.
Different from the safe conversion from a string to to a byte slice,
the unsafe way doesn't allocate a new underlying byte sequence
for the result slice in each conversion.

<pre class="line-numbers"><code class="language-go">package main

import (
	"fmt"
	"unsafe"
	"reflect"
	"runtime"
	"strings"
)

func String2ByteSlice(str string) (bs []byte) {
	strHdr := (*reflect.StringHeader)(unsafe.Pointer(&str))
	sliceHdr := (*reflect.SliceHeader)(unsafe.Pointer(&bs))
	sliceHdr.Data = strHdr.Data
	sliceHdr.Len = strHdr.Len
	sliceHdr.Cap = strHdr.Len
	// This KeepAlive line is essential to make the
	// String2ByteSlice function be always valid
	// when it is used in other custom packages.
	runtime.KeepAlive(&str)
	return
}

func main() {
	str := strings.Join([]string{"Go", "land"}, "")
	s := String2ByteSlice(str)
	fmt.Printf("%s\n", s) // Goland
	s[5] = 'g'
	fmt.Println(str) // Golang
}
</code></pre>

<p>
<a href="https://golang.org/pkg/reflect/#SliceHeader">The docs</a>
of the <code>SliceHeader</code> and <code>StringHeader</code> types in the
<code>reflect</code> standard package are similar.
The docs says the representations of the two struct types may change in a later release.
So the above example may become invalid even if the unsafe rules keep unchanged.
Fortunately, the current two available Go compilers (the standard Go compiler and the gccgo compiler)
both recognize the representations of the two types declared
in the <code>reflect</code> standard package.
</p>

It is also possible to convert a byte slice to a string by using a similar way.
However, currently (Go 1.13), there is a simpler but more efficient (and more unsafe) way to convert
a byte slice to a string.

<pre class="line-numbers"><code class="language-go">func ByteSlice2String(bs []byte) string {
	return *(*string)(unsafe.Pointer(&bs))
}
</code></pre>

<p>
This is the implementation adopted by the <code>String</code> method
of the <code>Builder</code> type supported since Go 1.10 in the
<code>strings</code> standard package.
It makes use of the first pattern introduced above.
</p>

In fact, in practice, to avoid the danger caused by missing <code>runtime.KeepAlive</code> calls,
it is more recommended to define our own custom <code>SliceHeader</code> and <code>StringHeader</code>
struct types which hold <code>Data</code> fileds of the <code>unsafe.Pointer</code> type instead of
the <code>uintptr</code> type. For example,

<pre class="line-numbers"><code class="language-go">type SliceHeader struct {
	Data unsafe.Pointer
	Len  int
	Cap  int
}

type StringHeader struct {
	Data unsafe.Pointer
	Len  int
}

func String2ByteSlice(str string) (bs []byte) {
	strHdr := (*StringHeader)(unsafe.Pointer(&str))
	sliceHdr := (*SliceHeader)(unsafe.Pointer(&bs))
	sliceHdr.Data = strHdr.Data
	sliceHdr.Len = strHdr.Len
	sliceHdr.Cap = strHdr.Len
	
	// The KeepAlive call is unessential now.
	//runtime.KeepAlive(&str)
	return
}
</code></pre>

<p>
</p>


</div>

<h3>Final Words</h3>

<p>
From the above content, we know that, for some cases,
the unsafe mechanism can help us write more efficient Go code.
However, it is very easy to introduce some subtle bugs which have
very low possibilities to produce when using the unsafe mechanism.
A program with these bugs may run well for a long time,
but suddenly behave abnormally and even crash at a later time.
Such bugs are very hard to detect and debug.
</p>

<p>
We should only use the unsafe mechanism when we have to,
and we must use it with extreme care.
In particular, we should follow the instructions described above.
</p>

<p>
And again, we should aware that the unsafe mechanism introduced above
may change and even become invalid totally in later Go versions,
though no evidences this will happen soon.
If the unsafe mechanism rules change,
the above introduced valid unsafe pointer use patterns may become invalid.
So please keep it easy to switch back to the safe implementations
for you code depending on the unsafe mechanism.
</p>


<!--

https://groups.google.com/forum/#!topic/golang-nuts/Ecwbd8SMoO0

https://github.com/golang/go/issues/34684
syscall.Proc.Call and syscall.LazyProc.Call are not implemented in assembly, and, as such, this rule does not apply to them.

-->

